#include "CharsetsPlugin.h"

#include <QtCore>
#include <QtGui/QAction>
#include <QtGui/QTreeWidget>

#include <juffed/CharsetsSettings.h>

#include "CharsetsDlg.h"

CharsetsPlugin::CharsetsPlugin() : QObject(), JuffPlugin() {
	action_ = new QAction(tr("Select charset"), 0);
	action_->setShortcut(QKeySequence("Shift+Ctrl+C"));
	connect(action_, SIGNAL(triggered()), SLOT(actionTriggered()));
	
	
	initEncodings();
	
	w_ = new QTreeWidget();
	connect(w_, SIGNAL(itemChanged(QTreeWidgetItem*, int)), SLOT(onItemChanged(QTreeWidgetItem*, int)));
	
	QHash<QString, EncList>::iterator it = encodings_.begin();
	while ( it != encodings_.end() ) {
		QString group = it.key();
		EncList& encList = it.value();
		QTreeWidgetItem* item = new QTreeWidgetItem(QStringList(group));
		w_->addTopLevelItem(item);
		EncList::iterator it2 = encList.begin();
		while ( it2 != encList.end() ) {
			QPair<QString, QString>& charset = *it2;
			QString encStr = charset.first;
			QString encName = charset.second;
			if ( encName.isEmpty() )
				encName = group;
			QString str = QString("%1 (%2)").arg(encName).arg(encStr);
			QTreeWidgetItem* subItem = new QTreeWidgetItem(item, QStringList() << str << encStr);
			bool enabled = CharsetsSettings::charsetEnabled(encStr);
			subItem->setCheckState(0, enabled ? Qt::Checked : Qt::Unchecked);
			it2++;
		}
		checkTopLevelItem(item);
		it++;
	}
}

CharsetsPlugin::~CharsetsPlugin() {
}

QString CharsetsPlugin::name() const {
	return "Charset selector";
}

QString CharsetsPlugin::targetEngine() const {
	return "all";
}

QString CharsetsPlugin::description() const {
	return "Lets to select charsets quickly from a popup dialog";
}

Juff::ActionList CharsetsPlugin::mainMenuActions(Juff::MenuID id) const {
	Juff::ActionList list;
	if ( id == Juff::ID_MENU_FORMAT )
		list << action_;
	return list;
}

void CharsetsPlugin::actionTriggered() {
	CharsetsDlg dlg(this, manager()->mainWindow());
	if ( dlg.exec() == QDialog::Accepted ) {
		manager()->setCurDocCharset(dlg.currentCharset());
		// TODO : add here setting the charset after 
		// this method added to ManagerInterface
	}
}

void CharsetsPlugin::onItemChanged(QTreeWidgetItem* item, int) {
	static bool started = false;
	if ( started )
		return;
	
	int index = w_->indexOfTopLevelItem(item);
	if ( index >= 0 ) {
		// this is a top level item
		int nSubItems = item->childCount();
		Qt::CheckState checked = item->checkState(0);
		started = true;
		for ( int i = 0; i < nSubItems; ++i ) {
			QTreeWidgetItem* subItem = item->child(i);
			subItem->setCheckState(0, checked);
		}
		started = false;
	}
	else {
		// this is not a top level item
		started = true;
		checkTopLevelItem(item->parent());
		started = false;
	}
}

void CharsetsPlugin::checkTopLevelItem(QTreeWidgetItem* item) {
	int index = w_->indexOfTopLevelItem(item);
	if ( index >= 0 ) {
		int nSubItems = item->childCount();
		int nCheckedSubItems = 0;
		for ( int i = 0; i < nSubItems; ++i ) {
			QTreeWidgetItem* subItem = item->child(i);
			if ( subItem->checkState(0) == Qt::Checked )
				nCheckedSubItems++;
		}
		
		if ( nCheckedSubItems == 0 )
			item->setCheckState(0, Qt::Unchecked);
		else if ( nCheckedSubItems < nSubItems )
			item->setCheckState(0, Qt::PartiallyChecked);
		else
			item->setCheckState(0, Qt::Checked);
	}
}

QWidget* CharsetsPlugin::settingsPage() const {
	return w_;
}

void CharsetsPlugin::saveSettings() {
	int n = w_->topLevelItemCount();
	for ( int i = 0; i < n; ++i ) {
		QTreeWidgetItem* item = w_->topLevelItem(i);
		int m = item->childCount();
		for ( int j = 0; j < m; ++j ) {
			QTreeWidgetItem* subItem = item->child(j);
			QString str = subItem->text(1);
			CharsetsSettings::setCharsetEnabled(str, subItem->checkState(0) == Qt::Checked);
		}
	}
}

void CharsetsPlugin::initEncodings() {
	EncList wEurope;
	wEurope << Enc("ISO 8859-1", "");
	wEurope << Enc("ISO 8859-15", "");
	wEurope << Enc("IBM 850", "");
	wEurope << Enc("Apple Roman", "");
	wEurope << Enc("Windows-1252", "");
	wEurope << Enc("ISO 8859-14", "Kelt");
	wEurope << Enc("ISO 8859-7", "Greek");
	wEurope << Enc("Windows-1253", "Greek");
	wEurope << Enc("ISO 8859-10", "Scandinavian");
	wEurope << Enc("ISO 8859-3", "South Europe");
	encodings_["Western Europe"] = wEurope;

	EncList eEurope;
	eEurope << Enc("ISO 8859-4", "Baltic");
	eEurope << Enc("ISO 8859-13", "Baltic");
	eEurope << Enc("Windows-1257", "Baltic");
	eEurope << Enc("ISO 8859-2", "Central Europe");
	eEurope << Enc("Windows-1250", "Central Europe");
	eEurope << Enc("ISO 8859-5", "Cyrillic");
	eEurope << Enc("KOI8-R", "Cyrillic");
	eEurope << Enc("Windows-1251", "Cyrillic");
	eEurope << Enc("IBM 866", "Cyrillic");
	eEurope << Enc("KOI8-U", "Cyrillic");
	eEurope << Enc("ISO 8859-16", "Romanian");
	encodings_["Eastern Europe"] = eEurope;

	EncList eAsia;
	eAsia << Enc("GB18030-0", "Chinese Simplified");
	eAsia << Enc("Big5", "Chinese Traditional");
	eAsia << Enc("Big5-HKSCS", "Chinese Traditional");
	eAsia << Enc("EUC-JP", "Japan");
	eAsia << Enc("EUC-KR", "Korea");
	encodings_["Eastern Asia"] = eAsia;

	EncList sAsia;
	sAsia << Enc("TIS-620", "Thai");
	sAsia << Enc("ISO 8859-9", "Turkish");
	sAsia << Enc("Windows-1254", "Turkish");
	sAsia << Enc("Windows-1258", "Vietnamese");
	encodings_["Southern Asia"] = sAsia;

	EncList mEast;
	mEast << Enc("ISO 8859-6", "Arabic");
	mEast << Enc("Windows-1256", "Arabic");
	mEast << Enc("ISO 8859-8", "Herbew");
	mEast << Enc("Windows-1255", "Herbew");
	encodings_["Middle East"] = mEast;

	EncList unicode;
	unicode << Enc("UTF-16", "");
	unicode << Enc("UTF-16BE", "");
	unicode << Enc("UTF-16LE", "");
	unicode << Enc("UTF-8", "");
	encodings_["Unicode"] = unicode;

	EncList other;
	other << Enc("IBM 874", "");
	other << Enc("ISO 2022-JP", "");
	other << Enc("Iscii-Bng", "");
	other << Enc("Iscii-Dev", "");
	other << Enc("Iscii-Gjr", "");
	other << Enc("Iscii-Knd", "");
	other << Enc("Iscii-Mlm", "");
	other << Enc("Iscii-Ori", "");
	other << Enc("Iscii-Pnj", "");
	other << Enc("Iscii-Tlg", "");
	other << Enc("Iscii-Tml", "");
	other << Enc("JIS X 0201", "");
	other << Enc("JIS X 0208", "");
	other << Enc("MuleLao-1", "");
	other << Enc("ROMAN8", "");
	other << Enc("Shift-JIS", "");
	other << Enc("TSCII", "");
	other << Enc("WINSAMI2", "");
	encodings_["Other"] = other;
}

Q_EXPORT_PLUGIN2(charsets, CharsetsPlugin)
